home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / pmenu.c < prev    next >
C/C++ Source or Header  |  1996-04-11  |  11KB  |  462 lines

  1. #include "pmenu.hpp"
  2.  
  3. void pmenu::move(int new_x, int new_y)
  4. {
  5.   wm->move_window(bar,new_x,new_y);
  6. }
  7.  
  8. pmenu::pmenu(int X, int Y, pmenu_item *first, image *screen, window_manager *wmanager)
  9.   top=first; 
  10.   active=NULL; 
  11.   wm=wmanager;
  12.  
  13.   short cx1,cy1,cx2,cy2;
  14.   screen->get_clip(cx1,cy1,cx2,cy2);
  15.   if (cx1<X) cx1=X;
  16.   int w=cx2-cx1+1;
  17.   int h=wm->font()->height()+4;
  18.  
  19.  
  20.   bar=wm->new_window(X,Y,w-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT,
  21.              h-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM,NULL);
  22.   bar->set_moveability(0);  // can't drag this window
  23.   bar->screen->wiget_bar(0,0,w-1,h-1,wm->bright_color(),wm->medium_color(),
  24.             wm->dark_color());
  25.  
  26.  
  27.  
  28.   int total=0,tx,tw;
  29.   pmenu_item *p=top;
  30.   for (;p;p=p->next) total++;
  31.  
  32.   tw=w/(total+1);
  33.   tx=tw/2;
  34.  
  35.   for (p=top;p;p=p->next,tx+=tw) 
  36.     p->draw_self(bar,itemx(p,wm),1,itemw(p,wm),1,wm,p==active);      
  37. /*  }
  38.   else
  39.   {
  40.     for (p=top;p;p=p->next,tx+=tw) 
  41.       p->draw(bar,itemx(p,wm),1,itemw(p,wm),1,wm,p==active);
  42.   }*/
  43.   
  44. }
  45.  
  46. pmenu_item::pmenu_item(int ID, char *Name, char *on_off_flag, int Hotkey, pmenu_item *Next)
  47.   xp=-1;
  48.   id=ID; 
  49.   hotkey=Hotkey;
  50.   on_off=on_off_flag;
  51.   if (Name)
  52.     n=strcpy((char *)jmalloc(strlen(Name)+1,"pmenu_item::name"),Name); 
  53.   else n=NULL;
  54.   next=Next;
  55.   sub=NULL;
  56. }
  57.  
  58. pmenu_item::pmenu_item(char *Name, psub_menu *Sub, pmenu_item *Next, int xpos)
  59. {
  60.   xp=xpos;
  61.   id=0; hotkey=-1;
  62.   next=Next;
  63.   on_off=NULL;
  64.   CONDITION(Name,"Sub menu cannot have a NULL name");
  65.   n=strcpy((char *)jmalloc(strlen(Name)+1,"pmenu_item::name"),Name); 
  66.   sub=Sub;
  67. }
  68.  
  69. pmenu_item *pmenu_item::find_id(int search_id) 
  70.   if (id==search_id) return this;
  71.   else if (sub) return sub->find_id(search_id);
  72.   else return NULL;
  73. }
  74.  
  75. pmenu_item *pmenu_item::find_key(int key)
  76. {
  77.   if (key==hotkey && hotkey!=-1) return this;
  78.   else if (sub) return sub->find_key(key);
  79.   else return NULL;
  80. }
  81.  
  82. pmenu::~pmenu()
  83. {
  84.   while (top)
  85.   {
  86.     pmenu_item *p=top;
  87.     top=top->next;
  88.     delete p;
  89.   }
  90.   if (bar) wm->close_window(bar);
  91. }
  92.  
  93. psub_menu::~psub_menu() 
  94.   if (win)   
  95.     wm->close_window(win);
  96.     
  97.   while (first)
  98.   {
  99.     pmenu_item *tmp=first;
  100.     first=first->next;
  101.     delete tmp;
  102.   }
  103. }
  104.  
  105. pmenu_item *psub_menu::find_id(int search_id)
  106. {
  107.   for (pmenu_item *f=first;f;f=f->next)
  108.   {
  109.     pmenu_item *ret=f->find_id(search_id);
  110.     if (ret) return ret;
  111.   }
  112.   return NULL;
  113. }
  114.  
  115. pmenu_item *psub_menu::find_key(int key)
  116. {
  117.   for (pmenu_item *f=first;f;f=f->next)
  118.   {
  119.     pmenu_item *ret=f->find_key(key);
  120.     if (ret) return ret;
  121.   }
  122.   return NULL;
  123. }
  124.  
  125.  
  126. void psub_menu::hide(jwindow *parent, int x, int y, window_manager* wm)
  127. {
  128.   int w,h;
  129.   calc_size(w,h,wm);
  130.   short cx1,cy1,cx2,cy2;
  131.   screen->get_clip(cx1,cy1,cx2,cy2);
  132.   if (w+x>cx2)
  133.     x=cx2-w;
  134.  
  135.  
  136.   if (win)
  137.   {
  138.     if (active!=-1)
  139.     {
  140.       int w,h;
  141.       calc_size(w,h,wm);
  142.       item_num(active)->draw(win,x+3,y+3+active*(wm->font()->height()+1),w-6,0,wm,0);
  143.     }
  144.     wm->close_window(win);
  145.     win=NULL;
  146.   }
  147. }
  148.  
  149. void psub_menu::calc_size(int &w, int &h, window_manager *wm)
  150. {
  151.   int tw=wm->font()->width(),th=wm->font()->height();
  152.   w=h=0;
  153.   for (pmenu_item *p=first;p;p=p->next)
  154.   {
  155.     if (p->name())
  156.     {
  157.       int l=strlen(p->name())*tw+8;
  158.       if (p->on_off) l+=tw*4;
  159.       if (l>w) w=l;   
  160.     }
  161.     h++;
  162.   }
  163.   h=h*(th+1)+8;
  164. }
  165.  
  166. void psub_menu::draw(jwindow *parent, int x, int y, window_manager *wmanager)
  167. {
  168.   if (win) wm->close_window(win);
  169.   wm=wmanager;
  170.  
  171.  
  172.   int w,h,i=0;
  173.   calc_size(w,h,wm);
  174.   short cx1,cy1,cx2,cy2;
  175.   screen->get_clip(cx1,cy1,cx2,cy2);
  176.   if (parent->x+w+x>cx2)
  177.     x=cx2-w-parent->x;
  178.   if (h+y+parent->y>cy2)
  179.     if (parent->y+parent->h+wm->font()->height()>cy2)
  180.       y=-h;
  181.      else y=y-h+wm->font()->height()+5;
  182.      
  183.  
  184.   win=wm->new_window(parent->x+x,parent->y+y,
  185.              w-WINDOW_FRAME_LEFT-WINDOW_FRAME_RIGHT,
  186.              h-WINDOW_FRAME_TOP-WINDOW_FRAME_BOTTOM,NULL);
  187.   win->set_moveability(0);
  188.   win->screen->wiget_bar(0,0,w-1,h-1,wm->bright_color(),wm->medium_color(),wm->dark_color());
  189.  
  190.   int has_flags=0;
  191.   pmenu_item *p=first;
  192.   for (;p;p=p->next) if (p->on_off) has_flags=1;
  193.   x=has_flags ? 3+wm->font()->width() : 3;
  194.   y=3;
  195.  
  196.   for (p=first;p;p=p->next,i++,y+=wm->font()->height()+1)
  197.     p->draw(win,x,y,w-6,0,wm,i==active);
  198.  
  199. }
  200.  
  201. void pmenu_item::draw_self(jwindow *parent, int x, int y, int w, int top, window_manager *wm, int active)
  202. {
  203.   int bx=x;
  204.   if (on_off) bx=x-wm->font()->width();
  205.  
  206.   if (!n)
  207.   {
  208.     int h=wm->font()->height();
  209.     parent->screen->wiget_bar(x,y+h/2-1,x+w-1,y+h/2,wm->dark_color(),wm->medium_color(),wm->bright_color());
  210.   } else
  211.   {
  212.     if (active)
  213.     {
  214.       if (xp!=-1)
  215.         parent->screen->xor_bar(bx,y,x+w-1,y+wm->font()->height()+1,wm->dark_color());
  216.       else
  217.       {
  218.     parent->screen->bar(bx,y,x+w-1,y+wm->font()->height()+1,wm->dark_color());
  219.     wm->font()->put_string(parent->screen,x+1,y+1,n,wm->medium_color());    
  220.     if (on_off && *on_off) wm->font()->put_string(parent->screen,bx+1,y+1,"*",wm->medium_color());
  221.       }
  222.     } else
  223.     {
  224.       if (xp!=-1)
  225.         parent->screen->xor_bar(bx,y,x+w-1,y+wm->font()->height()+1,wm->dark_color());
  226.       else
  227.       {
  228.     parent->screen->bar(bx,y,x+w-1,y+wm->font()->height()+1,wm->medium_color());
  229.     wm->font()->put_string(parent->screen,x+1,y+1,n,wm->bright_color());
  230.     if (on_off && *on_off) wm->font()->put_string(parent->screen,bx+1,y+1,"*",wm->bright_color());
  231.       }
  232.     }
  233.   }
  234. }
  235.  
  236. void pmenu_item::draw(jwindow *parent, int x, int y, int w, int top,
  237.               window_manager *wm, int active)
  238. {  
  239.   if (n)
  240.   {
  241.     if (active)
  242.     {      
  243.       draw_self(parent,x,y,w,top,wm,active);
  244.       if (sub)
  245.       {
  246.     if (top)
  247.           sub->draw(parent,x,y+wm->font()->height()+2,wm);
  248.     else
  249.       sub->draw(parent,x+w,y,wm);
  250.       }
  251.     }
  252.     else
  253.     {
  254.       if (sub)
  255.       {
  256.     if (top)
  257.           sub->hide(parent,x,y+wm->font()->height()+2,wm);
  258.     else
  259.       sub->hide(parent,x+w,y,wm);
  260.       }
  261.       draw_self(parent,x,y,w,top,wm,active);
  262.  
  263.     }
  264.  
  265.   } else draw_self(parent,x,y,w,top,wm,active);
  266. }
  267.  
  268. int pmenu::itemx(pmenu_item *p, window_manager *wm)
  269. {
  270.   if (p->xp!=-1) return p->xp;
  271.   int w=bar->screen->width();
  272.   
  273.  
  274.   int total=0,tx,tw,i=0,x;
  275.   for (pmenu_item *pp=top;pp;pp=pp->next,i++) 
  276.   { if (pp==p) x=i;
  277.     total++;
  278.   }
  279.  
  280.   
  281.   tw=w/(total+1); 
  282.   return tw/2+x*tw;
  283. }
  284.  
  285.  
  286. void pmenu::draw(image *screen, window_manager *wm, int top_only)
  287. {
  288.  
  289. }
  290.  
  291.  
  292. int psub_menu::handle_event(jwindow *parent, int x, int y, window_manager *wm, event &ev)
  293. {
  294.   int w,h;
  295.   calc_size(w,h,wm);
  296.   short cx1,cy1,cx2,cy2;
  297.   screen->get_clip(cx1,cy1,cx2,cy2);
  298.  
  299.   x=win->x;
  300.   y=win->y;
  301.  
  302.   int has_flags=0,dx=3;
  303.   for (pmenu_item *p=first;p;p=p->next) if (p->on_off) has_flags=1;
  304.   if (has_flags) dx+=wm->font()->width();
  305.  
  306.   int th=wm->font()->height();
  307.   if (ev.mouse_move.x>=x && ev.mouse_move.y>=y && ev.mouse_move.x<x+w && ev.mouse_move.y<y+h)
  308.   {
  309.     int new_active=(ev.mouse_move.y-y-3)/(th+1);
  310.     if (item_num(new_active)==NULL) new_active=-1;
  311.  
  312.     if (new_active!=active)
  313.     {
  314.       if (active!=-1)
  315.         item_num(active)->draw(win,dx,3+active*(th+1),w-6,0,wm,0);
  316.       active=new_active;
  317.       if (active!=-1)
  318.         item_num(active)->draw(win,dx,3+active*(th+1),w-6,0,wm,1);
  319.     }
  320.     if (ev.type==EV_MOUSE_BUTTON)
  321.     {
  322.       if (active!=-1)
  323.         return item_num(active)->handle_event(win,dx,3+active*(th+1),w-6,0,wm,ev);
  324.       else return 0;
  325.     } else return 1;
  326.   } else if (active!=-1)
  327.     return item_num(active)->handle_event(win,win->x+dx,win->y+3+active*(th+1),w-6,0,wm,ev);
  328.   else return 0;
  329.  
  330.  
  331. }
  332.  
  333. int pmenu_item::handle_event(jwindow *parent, int x, int y, int w, int top, 
  334.                  window_manager *wm, event &ev)
  335. {
  336.   x+=parent->x;
  337.   y+=parent->y;
  338.   if (ev.mouse_move.x>=x && ev.mouse_move.y>=y && ev.mouse_move.x<x+w &&
  339.       ev.mouse_move.y<y+wm->font()->height()+2)
  340.   {
  341.     if (sub) return 1;
  342.     else 
  343.     {
  344.       if (ev.type==EV_MOUSE_BUTTON &&n)
  345.         wm->push_event(new event(id,(char *)this));
  346.       return 1;
  347.     }    
  348.   } else if (sub)
  349.   { 
  350.     if (top)
  351.       return sub->handle_event(parent,x,y+wm->font()->height()+2,wm,ev);
  352.     else return sub->handle_event(parent,x+w,y,wm,ev);
  353.   } else return 0;
  354. }
  355.  
  356. pmenu_item *pmenu::inarea(int mx, int my, image *screen, window_manager *wm) 
  357.   short cx1,cy1,cx2,cy2;
  358.   screen->get_clip(cx1,cy1,cx2,cy2);  
  359.   mx-=bar->x;
  360.   my-=bar->y;
  361.   if (mx<0 || my<0 || mx>=bar->screen->width() || my>=bar->screen->height()) return NULL;
  362.   else 
  363.   {
  364.     for (pmenu_item *p=top;p;p=p->next)
  365.     {
  366.       if (!p->next) return p;
  367.       else if (itemx(p->next,wm)>mx) return p;
  368.     }
  369.     return NULL;
  370.   }
  371. }
  372.  
  373. int psub_menu::own_event(event &ev) 
  374.   if (win && ev.window==win) return 1; else
  375.     for (pmenu_item *p=first;p;p=p->next)
  376.       if (p->own_event(ev)) 
  377.         return 1; 
  378.   return 0; 
  379. }
  380.  
  381. int pmenu_item::own_event(event &ev) 
  382.   if (sub) 
  383.     return sub->own_event(ev); 
  384.   else return 0; 
  385. }
  386.  
  387. pmenu_item::~pmenu_item() 
  388. { if (n) jfree(n); if (sub) delete sub; 
  389. }
  390.  
  391. int pmenu::handle_event(event &ev, image *screen, window_manager *wm)
  392. {
  393.   if (!active && ev.window!=bar) return 0;
  394. /* 
  395.     int yes=0;
  396.     if (ev.window==bar) yes=1;    // event in top bar?
  397.     else
  398.     {
  399.       for (pmenu_item *p=top;p && !yes;p=p->next)  // event in submenu?
  400.       if (p->own_event(ev)) yes=1;
  401.     }
  402.     if (!yes) return 0;        // event is not for us...
  403.   }*/
  404.  
  405.   switch (ev.type)
  406.   {
  407.     case EV_KEY :
  408.     {
  409.       for (pmenu_item *p=top;p;p=p->next)
  410.       { 
  411.     pmenu_item *r=p->find_key(ev.key);
  412.     if (r)
  413.     { 
  414.       wm->push_event(new event(r->id,(char *)r));
  415.       return 1;
  416.     }
  417.       }
  418.       return 0;
  419.     } break;
  420.     case EV_MOUSE_MOVE :
  421.     {
  422.       pmenu_item *new_selection=inarea(ev.mouse_move.x,ev.mouse_move.y,screen,wm);
  423.       if (!new_selection && active && 
  424.       active->handle_event(bar,itemx(active,wm),1,itemw(active,wm),1,wm,ev))
  425.     return 1;
  426.       else if (active!=new_selection)
  427.       {
  428.     if (active)
  429.       active->draw(bar,itemx(active,wm),1,itemw(active,wm),1,wm,0);
  430.     active=new_selection;
  431.     if (active)
  432.       active->draw(bar,itemx(active,wm),1,itemw(active,wm),1,wm,1);
  433.       }
  434.       if (active) return 1;
  435.       else return 0;
  436.     } break;
  437.     case EV_MOUSE_BUTTON :
  438.     {
  439.       if (active) 
  440.       {
  441.         if (active->handle_event(bar,itemx(active,wm),1,itemw(active,wm),1,wm,ev))
  442.     {
  443.       active->draw(bar,itemx(active,wm),1,itemw(active,wm),1,wm,0);
  444.       active=NULL;
  445.       return 1;
  446.     } else return 0;
  447.       }
  448.       else return 0;
  449.     } break;
  450.   }
  451.   return 0;
  452. }
  453.  
  454.  
  455.